package com.tingyuge.thinking.spring.dependency.injection;

import com.tingyuge.thinking.spring.dependency.injection.annotation.InjectedUser;
import com.tingyuge.thinking.spring.dependency.injection.annotation.MyAutowired;
import com.tingyuge.thinking.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

import javax.inject.Inject;
import javax.swing.text.html.Option;
import java.lang.annotation.Annotation;
import java.util.*;

import static org.springframework.context.annotation.AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME;

/**
 * {@link DependencyDescriptor} 实现延迟注入
 *
 * @author xiaodao
 * @version 1.0
 * @date 2021/6/29
 */
public class AnnotationDependencyResolutionInjectionDemo {


    //实时注入--DependencyDescriptor-->
    // 必须(required=true)
    // 实时注入(eager=true)
    // 通过类型查找的方法 (User.class)+字段名称("user")
    @Autowired
    private User user;

    @Autowired //集合类型的依赖注入
    private Map<String, User> users;

    @Inject
    private User injectUser;


    @MyAutowired
    private Optional<User> userOptional;//supperUser

    @InjectedUser
    private User injectedUser;

    /**
     * @bean 如果是static 会提早出发
     * @return
     */
/*
    @Bean(name = AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)
    public static AutowiredAnnotationBeanPostProcessor beanPostProcessor(){
        AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
        //替换原有注解处理.使用新注解@autowired + @inject + @injectUser
        Set<Class<? extends Annotation>> autowiredAnnotationSet = new LinkedHashSet<>(Arrays.asList(Autowired.class, Inject.class, InjectedUser.class));
        beanPostProcessor.setAutowiredAnnotationTypes(autowiredAnnotationSet);
        return beanPostProcessor;
    }
*/

    /**
     * 会注册俩个 AutowiredAnnotationBeanPostProcessor
     * @return
     */
    @Bean
    @Order(Ordered.LOWEST_PRECEDENCE-3)
    public static AutowiredAnnotationBeanPostProcessor beanPostProcessor(){
        AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
        //替换原有注解处理.使用新注解@autowired + @inject + @injectUser
        Set<Class<? extends Annotation>> autowiredAnnotationSet = new LinkedHashSet<>(Arrays.asList(Autowired.class, Inject.class, InjectedUser.class));
        beanPostProcessor.setAutowiredAnnotationTypes(autowiredAnnotationSet);
        return beanPostProcessor;
    }


    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        //注册 configuration class（配置类）
        applicationContext.register(AnnotationDependencyResolutionInjectionDemo.class);

        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
        String xmlClassPath = "classpath:/META-INF/dependency-lookup-context.xml";
        beanDefinitionReader.loadBeanDefinitions(xmlClassPath);
        //通过BeanDefinition 注册API 方式
        //启动应用上下文
        applicationContext.refresh();
        AnnotationDependencyResolutionInjectionDemo demo = applicationContext.getBean(AnnotationDependencyResolutionInjectionDemo.class);
        //输出primary User
        System.out.println("demo.user:" + demo.user);
        System.out.println("demo.user:" + demo.injectUser);
        System.out.println();
        System.out.println("demo.users:" + demo.users);
        System.out.println("demo.userOptional:" + demo.userOptional);
        System.out.println("demo.injectedUser:" + demo.injectedUser);


        //显示关闭应用上下文
        applicationContext.close();
    }
}
